package org.opens.service;

import org.opens.entity.Person;

import java.util.List;
import java.util.Optional;

/**
 * @Date 2021/2/1 19:40
 * @Created by 99126
 */
public interface PersonService {

    void save(Person person);

    void deleteById(Integer id);

    Optional<Person> findById(Integer id);

    Person updateById(Person person);

    int insertByRequiredFail(Person person);

    int batchInsertByRequiredFail(List<Person> personList);

    int ageIncByREQUIRED(int id);

    /**
     * 测试在事务中先删除后插入是否可以成功插入.
     * 输出:
     * ```
     * Creating a new SqlSession
     * Registering transaction synchronization for SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@4eb9f2af]
     * JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@ffd4cba] will be managed by Spring
     * ==>  Preparing: DELETE FROM person WHERE id=?
     * ==> Parameters: 1(Integer)
     * <==    Updates: 1
     * Releasing transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@4eb9f2af]
     * 2023-04-19 17:58:48.135  INFO 1584 --- [           main] o.opens.service.impl.PersonServiceImpl   : 删除影响行: 1
     * Fetched SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@4eb9f2af] from current transaction
     * ==>  Preparing: SELECT id,address,id_card,name,age,create_date FROM person WHERE id=?
     * ==> Parameters: 1(Integer)
     * <==      Total: 0
     * Releasing transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@4eb9f2af]
     * 2023-04-19 17:58:48.156  INFO 1584 --- [           main] o.opens.service.impl.PersonServiceImpl   : 删除后, 根据id查到的对象: null
     * Fetched SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@4eb9f2af] from current transaction
     * ==>  Preparing: INSERT INTO person ( id_card ) VALUES ( ? )
     * ==> Parameters: 123(String)
     * <==    Updates: 1
     * Releasing transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@4eb9f2af]
     * 2023-04-19 17:58:48.210  INFO 1584 --- [           main] o.opens.service.impl.PersonServiceImpl   : 最后, 进行插入测试: 1
     * ```
     * 结论:
     * - 同一个事务中, 对数据的修改是可以立刻看到的, 所以, 同一个事务中删掉后立即进行插入是可以成功的.
     */
    void deleteBeforeInserting();

    /**
     * 测试在事务方法中想脱离事务如何操作.
     * 输出:
     * ```
     * Creating a new SqlSession
     * Registering transaction synchronization for SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@2e32fc22]
     * JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@217bf99e] will be managed by Spring
     * ==>  Preparing: INSERT INTO person ( id_card, name ) VALUES ( ?, ? )
     * ==> Parameters: 456(String), s123(String)
     * <==    Updates: 1
     * Releasing transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@2e32fc22]
     * Transaction synchronization suspending SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@2e32fc22]
     * Creating a new SqlSession
     * Registering transaction synchronization for SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@315105f]
     * JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@18b74ea] will be managed by Spring
     * ==>  Preparing: INSERT INTO method_log ( method_name ) VALUES ( ? )
     * ==> Parameters: insertAndRecordLog(String)
     * <==    Updates: 1
     * Releasing transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@315105f]
     * Transaction synchronization deregistering SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@315105f]
     * Transaction synchronization closing SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@315105f]
     * Transaction synchronization resuming SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@2e32fc22]
     * Transaction synchronization deregistering SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@2e32fc22]
     * Transaction synchronization closing SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@2e32fc22]
     * ```
     * 结论:
     * - 将需要脱离的事务方法修饰@Transactional(propagation = Propagation.NOT_SUPPORTED)即可.
     * @param person 插入参数
     */
    void insertAndRecordLog(Person person);

    /**
     * 测试同一个事务方法中先插入后查询是否能查询到刚刚插入的数据
     * 结论:
     * - 可以查询到
     * @param person    插入对象
     */
    void insertAndSelect(Person person);

}
